package org.dreamwork.plugins.network.assistant.gui

import org.dreamwork.plugins.network.assistant.gui.NetworkReader.NetworkReaderListener
import java.io.IOException
import java.io.OutputStream
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import java.net.Socket
import java.util.concurrent.ExecutorService
import java.util.concurrent.Future

class TcpAdapter (private val socket: Socket) : INetworkAdapter {
    private var out: OutputStream = socket.getOutputStream ()
    @Throws(IOException::class)
    override fun write(data: ByteArray) {
        out.write(data)
    }

    @Throws(IOException::class)
    override fun close() {
        socket.close()
    }
}

class UdpAdapter (private val socket: DatagramSocket, packet: DatagramPacket) : INetworkAdapter {
    private val remote: InetAddress = packet.address
    private val port: Int = packet.port

    @Throws(IOException::class)
    override fun write(data: ByteArray) {
        val packet = DatagramPacket(data, data.size, remote, port)
        socket.send(packet)
    }

    override fun close() {
    }
}

class TcpClientWorker (
        private val socket: Socket,
        executor: ExecutorService,
        private val listener: TcpClientListener?) : NetworkReaderListener {
    var name: String = socket.remoteSocketAddress.toString()

    //    private val socket: Socket?
    private val out: OutputStream = socket.getOutputStream()
    private val reader: TcpReader = TcpReader(socket.getInputStream())
    private val future: Future<*> = executor.submit(reader)

    override fun onClosed() {
        listener?.onDisconnected(this)
    }

    override fun onReceived(data: ByteArray?) {
        listener?.onReceived(data)
    }

    interface TcpClientListener {
        fun onConnected(worker: TcpClientWorker?)
        fun onDisconnected(worker: TcpClientWorker?)
        fun onReceived(data: ByteArray?)
    }

//    private val listener: TcpClientListener?

    @Throws(IOException::class)
    fun write(data: ByteArray) {
        out.write(data)
    }

    @Throws(IOException::class)
    fun close() {
        socket.close()
        future.cancel(true)
        reader.shutdown()
    }

    init {
        reader.listener = this
        listener?.onConnected(this)
    }
}
